package com.jumi.microservice.service;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jumi.microservice.common.constant.InventoryRedisKey;
import com.jumi.microservice.constant.ExceptionEnum;
import com.jumi.microservice.domain.CommodityRenderApplyDTO;
import com.jumi.microservice.domain.GoodsSkuStockDTO;
import com.jumi.microservice.domain.GoodsStockDO;
import com.jumi.microservice.domain.GoodsWarehouseStockDO;
import com.jumi.microservice.mapper.GoodsStockMapper;
import com.jumi.microservice.mapper.GoodsWarehouseStockMapper;
import com.jumi.microservice.stock.dto.commodity.CommodityApplyDetailDTO;
import com.jumi.microservice.stock.dto.commodity.CommodityRenderDTO;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RestController;

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * - - - - - - - - - - - - - - -
 *
 * @author liuz
 * @date 2020/9/11 17:11
 * ToDoSomeThing
 * - - - - - - - - - - - - - - -
 */
@DubboService
@Transactional
public class SupplyInventoryService implements InventoryApi {

    private static final Logger logger = LoggerFactory.getLogger(SupplyInventoryService.class);

    @Autowired
    private GoodsWarehouseStockMapper warehouseStockMapper;

    @Autowired
    private GoodsStockMapper goodsStockMapper;

    @Autowired
    RedisTemplate redisTemplate;

    /**
     * 供应链物料分仓
     * @param commodityRenderApply sku库存及分仓信息
     * @return
     */
    @Override
    public void  supplySubWarehouse(CommodityRenderApplyDTO commodityRenderApply) {

        logger.info("供应链分仓调用参数:{}", JSONObject.toJSONString(commodityRenderApply));

        Long spuId = commodityRenderApply.getSpuId();
        ExceptionEnum.FAIL_SUPPLY_SPUID_NULL.doThrowIf(spuId==null);
        //用于计算sku的总库存 供应链只计算分仓后sku的库存
        Map<Long,Integer> skuStockMap = new HashMap<>();
        //用于计算预售转实际的预售库存
        Map<Long,Integer> preSkuStockMap = new HashMap<>();
        List<Long> skuIds = new ArrayList<>();
        List<Long> wareIds = new ArrayList<>();
        //处理sku的分仓信息
        commodityRenderApply.getCommodityRenderDTOS().forEach(dto->{
            skuIds.add(dto.getSkuId());
            wareIds.add(dto.getWarehouseId());
        });
        //空skuid返回
        if(CollectionUtil.isEmpty(skuIds)){
            return;
        }
        List<GoodsWarehouseStockDO> warehouseStockes = warehouseStockMapper.selectList(
                Wrappers.<GoodsWarehouseStockDO>lambdaQuery()
                        .in(GoodsWarehouseStockDO::getGoodsSkuId, skuIds)
                        .in(GoodsWarehouseStockDO::getWarehouseId, wareIds));
        if(CollectionUtil.isNotEmpty(warehouseStockes)){
            warehouseStockes.stream().forEach(warehouseStockDO->{
                CommodityRenderDTO dto = commodityRenderApply.getCommodityRenderDTOS().stream()
                        .filter(com->warehouseStockDO.getGoodsSkuId().equals(com.getSkuId())&&warehouseStockDO.getWarehouseId().equals(com.getWarehouseId()))
                        .findAny()
                        .orElse(null);
                if(dto!=null) {
                    updateWare(warehouseStockDO, dto);
                    //如果map中已有sku的库存 累加
                    if(skuStockMap.get(dto.getSkuId())!=null){
                        skuStockMap.put(dto.getSkuId(),skuStockMap.get(dto.getSkuId())+dto.getRenderStockNum());
                    }else{
                        skuStockMap.put(dto.getSkuId(), dto.getRenderStockNum());
                    }
                    //判断如果是预售转的实际
                    if(1==dto.getType()){
                        //如果preSkuStockMap中已有sku的库存 累加
                        if(preSkuStockMap.get(dto.getSkuId())!=null){
                            preSkuStockMap.put(dto.getSkuId(),preSkuStockMap.get(dto.getSkuId())+dto.getRenderStockNum());
                        }else{
                            preSkuStockMap.put(dto.getSkuId(), dto.getRenderStockNum());
                        }
                    }
                }
            });
        }else {
            commodityRenderApply.getCommodityRenderDTOS().forEach(dto->{
                insertWare(dto);
                //如果map中已有sku的库存 累加
                if(skuStockMap.get(dto.getSkuId())!=null){
                    skuStockMap.put(dto.getSkuId(),skuStockMap.get(dto.getSkuId())+dto.getRenderStockNum());
                }else{
                    skuStockMap.put(dto.getSkuId(), dto.getRenderStockNum());
                }
                //判断如果是预售转的实际
                if(1==dto.getType()){
                    //如果preSkuStockMap中已有sku的库存 累加
                    if(preSkuStockMap.get(dto.getSkuId())!=null){
                        preSkuStockMap.put(dto.getSkuId(),preSkuStockMap.get(dto.getSkuId())+dto.getRenderStockNum());
                    }else{
                        preSkuStockMap.put(dto.getSkuId(), dto.getRenderStockNum());
                    }
                }
            });
        }
        //处理sku总库存信息
        List<GoodsStockDO> goodsStockes = goodsStockMapper.selectList(
                Wrappers.<GoodsStockDO>lambdaQuery()
                        .in(GoodsStockDO::getGoodsSkuId, skuIds));
        if(CollectionUtil.isNotEmpty(goodsStockes)){
            goodsStockes.stream().forEach(goodsStock->{
                CommodityApplyDetailDTO dto = commodityRenderApply.getDetails().stream()
                        .filter(com->goodsStock.getGoodsSkuId().equals(com.getSkuId()))
                        .findAny()
                        .orElse(null);
                //获取sku的库存
                if(skuStockMap.get(dto.getSkuId())!=null){
                    dto.setRenderStockNum(skuStockMap.get(dto.getSkuId()));
                }else{
                    dto.setRenderStockNum(0);
                }
                //判断如果preSkuStockMap存在 则为预售转真实的库存
                if(preSkuStockMap.get(dto.getSkuId())!=null){
                    dto.setPreStockNum(preSkuStockMap.get(dto.getSkuId()));
                    //临时变量处理 预售+或-
                    dto.setApplyId(-1L);
                }
                //更新库存信息
                update(dto, goodsStock);
            });
        }else{
            commodityRenderApply.getDetails().stream().forEach(dto->{
                //获取sku的库存
                if(skuStockMap.get(dto.getSkuId())!=null){
                    dto.setRenderStockNum(skuStockMap.get(dto.getSkuId()));
                }else{
                    dto.setRenderStockNum(0);
                }
                //判断如果preSkuStockMap存在 则为预售转真实的库存
                if(preSkuStockMap.get(dto.getSkuId())!=null){
                    dto.setPreStockNum(preSkuStockMap.get(dto.getSkuId()));
                    //临时变量处理 预售+或-
                    dto.setApplyId(-1L);
                }
                //添加库存信息
                inser(dto, spuId);
            });
        }

    }


    /**
     * 新增库存信息
     * @param dto
     */
    private void inser(CommodityApplyDetailDTO dto, Long spuId){
        GoodsStockDO goodsStock = new GoodsStockDO();
        goodsStock.setUpdateTime(LocalDateTime.now());
        goodsStock.setCreateTime(LocalDateTime.now());
        goodsStock.setGoodsSkuStorage(dto.getRenderStockNum());
        goodsStock.setGoodsSkuId(dto.getSkuId());
        goodsStock.setGoodsSkuCode(dto.getSkuCode());
        goodsStock.setGoodsId(spuId);
        goodsStock.setInitialPreStorage(dto.getPreStockNum());
        goodsStock.setPreStorage(dto.getPreStockNum());
        goodsStockMapper.insert(goodsStock);
//        redisSkuStock(goodsStock);
    }

    /**
     * 更新库存信息
     * @param dto
     */
    private void update(CommodityApplyDetailDTO dto, GoodsStockDO goodsStock){
        //暂时用先查再更新 累加库存
        goodsStock.setGoodsSkuStorage(goodsStock.getGoodsSkuStorage()+dto.getRenderStockNum());
        goodsStock.setUpdateTime(LocalDateTime.now());
        //-1L代表预售转实际 预售-值
        if(-1L==dto.getApplyId()) {
            goodsStock.setPreStorage(goodsStock.getPreStorage() - dto.getPreStockNum());
        }else{
            goodsStock.setPreStorage(goodsStock.getPreStorage() + dto.getPreStockNum());
            goodsStock.setInitialPreStorage(goodsStock.getInitialPreStorage() + dto.getPreStockNum());
        }
        goodsStockMapper.updateById(goodsStock);
//        if(CollectionUtil.isEmpty(redisTemplate.opsForHash().entries(InventoryRedisKey.GOODS_SKU_STOCK+goodsStock.getGoodsSkuId()))) {
//            redisSkuStock(goodsStock);
//        }else{
//            if(-1L==dto.getApplyId()) {
//                //预售转实际 预售库存-
//                redisSkuStockInc(InventoryRedisKey.GOODS_SKU_STOCK+goodsStock.getGoodsSkuId(),
//                        InventoryRedisKey.PRESTORAGE,
//                        -dto.getPreStockNum()
//                );
//            }else{
//                //分仓库存
//                redisSkuStockInc(InventoryRedisKey.GOODS_SKU_STOCK+goodsStock.getGoodsSkuId(),
//                        InventoryRedisKey.PRESTORAGE,
//                        dto.getPreStockNum()
//                );
//                redisSkuStockInc(InventoryRedisKey.GOODS_SKU_STOCK+goodsStock.getGoodsSkuId(),
//                        InventoryRedisKey.INITIALPRESTORAGE,
//                        dto.getPreStockNum()
//                );
//                redisSkuStockInc(InventoryRedisKey.GOODS_SKU_STOCK+goodsStock.getGoodsSkuId(),
//                        InventoryRedisKey.GOODSSKUSTORAGE,
//                        dto.getRenderStockNum()
//                );
//            }
//
//        }
    }

    /**
     * 分仓信息保存
     * @param dto
     */
    private void insertWare( CommodityRenderDTO dto){
        GoodsWarehouseStockDO warehouseStockDO = new GoodsWarehouseStockDO();
        warehouseStockDO.setSupplyApplyId(dto.getApplyId());
        warehouseStockDO.setCreateTime(LocalDateTime.now());
        warehouseStockDO.setCreateTime(LocalDateTime.now());
        warehouseStockDO.setGoodsSkuId(dto.getSkuId());
        warehouseStockDO.setWarehouseId(dto.getWarehouseId());
        warehouseStockDO.setWarehouseName(dto.getWarehouseName());
        warehouseStockDO.setGoodsSkuCode(dto.getSkuCode());
        warehouseStockDO.setSaleStockQuantity(dto.getRenderStockNum());
        warehouseStockMapper.insert(warehouseStockDO);
//        redisSkuWareStock(warehouseStockDO);
    }

    /**
     * 更新分仓信息
     * @param warehouseStockDO
     * @param dto
     */
    private void updateWare(GoodsWarehouseStockDO warehouseStockDO, CommodityRenderDTO dto){
        warehouseStockDO.setUpdateTime(LocalDateTime.now());
        warehouseStockDO.setSaleStockQuantity(warehouseStockDO.getSaleStockQuantity()+dto.getRenderStockNum());
        warehouseStockMapper.updateById(warehouseStockDO);
        //如果redis不存在直接存
//        if(CollectionUtil.isEmpty(redisTemplate.opsForHash().entries(
//                InventoryRedisKey.GOODS_SKU_WARE_STOCK+warehouseStockDO.getGoodsSkuId()+"-"+warehouseStockDO.getWarehouseId()))) {
//            redisSkuWareStock(warehouseStockDO);
//        }else{
//            //更新redis的库存
//            redisSkuStockInc(InventoryRedisKey.GOODS_SKU_WARE_STOCK+warehouseStockDO.getGoodsSkuId()+"-"+warehouseStockDO.getWarehouseId(),
//                    InventoryRedisKey.SALESTOCKQUANTITY,
//                    dto.getRenderStockNum());
//        }
    }

    /**
     * 同步redis 商品sku总库存
     * @param goodsStock
     */
    private void redisSkuStock(GoodsStockDO goodsStock){
        Map<String,Object> stockMap = new HashMap<>();
        stockMap.put(InventoryRedisKey.GOODSSKUSTOCKID, goodsStock.getId().toString());
        stockMap.put(InventoryRedisKey.GOODSSKUSTORAGE , goodsStock.getGoodsSkuStorage().toString());
        stockMap.put(InventoryRedisKey.PRESTORAGE, goodsStock.getPreStorage().toString());
        stockMap.put(InventoryRedisKey.INITIALPRESTORAGE, goodsStock.getInitialPreStorage().toString());
        stockMap.put(InventoryRedisKey.LOCKEDSTORAGE, goodsStock.getLockedStorage().toString());
        stockMap.put(InventoryRedisKey.SALEDSTORAGE, goodsStock.getSaledStorage().toString());
        stockMap.put(InventoryRedisKey.GOODS_TYPE, "0");
        redisTemplate.opsForHash().putAll(InventoryRedisKey.GOODS_SKU_STOCK+goodsStock.getGoodsSkuId(), stockMap);
    }

    /**
     * 同步redis 商品sku分仓 库存
     * @param warehouseStockDO
     */
    private void redisSkuWareStock(GoodsWarehouseStockDO warehouseStockDO){
        Map<String,Object> wareMap = new HashMap<>();
        wareMap.put(InventoryRedisKey.GOODSSKUSTOCKID, warehouseStockDO.getId().toString());
        wareMap.put(InventoryRedisKey.WAREHOUSEID, warehouseStockDO.getWarehouseId().toString());
        wareMap.put(InventoryRedisKey.SALESTOCKQUANTITY, warehouseStockDO.getSaleStockQuantity().toString());
        wareMap.put(InventoryRedisKey.LOCKEDSTOCKQUANTITY, warehouseStockDO.getLockedStockQuantity().toString());
        wareMap.put(InventoryRedisKey.SALEDSTOCKQUANTITY, warehouseStockDO.getSaledStockQuantity().toString());
        wareMap.put(InventoryRedisKey.SUPPLYAPPLYID, warehouseStockDO.getSupplyApplyId().toString());
        wareMap.put(InventoryRedisKey.GOODS_TYPE, "0");
        String key = InventoryRedisKey.GOODS_SKU_WARE_STOCK+warehouseStockDO.getGoodsSkuId()+":"+warehouseStockDO.getWarehouseId();
        redisTemplate.opsForHash().putAll(key, wareMap);
    }

    /**
     * 更新库存的库存值 自增
     * @param key redis的库存key
     * @param mapKey 商品库存的map中key
     * @param stockNum 库存量
     */
    private void redisSkuStockInc(String key, String mapKey ,Integer stockNum){
        redisTemplate.opsForHash().increment(key, mapKey, stockNum);
    }

}
